package com.itheima.aspect;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

/**
 * 通知类型
 */
//@Component // 放到IOC容器中
@Aspect // 标记是一个切面类
@Slf4j
public class AdviceTypeAspect {
    /**
     * 环绕通知，目标方法请求前和请求后都会执行
     */
    @Around("execution(* com.itheima.service.impl.*.* (..))")
    public Object aroundAdvice(ProceedingJoinPoint pj) throws Throwable {
        log.info("环绕通知，目标方法请求前通知...");
        // 调用目标方法
        Object proceed = pj.proceed();
        // 如果出现异常了，目标方法请求后，就不会执行啦。
        log.info("环绕通知，目标方法请求后通知...");
        return proceed;
    }

    /**
     * 前置通知，目标方法请求前会执行
     */
    @Before("execution(* com.itheima.service.impl.*.* (..))")
    public void beforeAdvice(JoinPoint jp)  {
        log.info("前置通知，目标方法请求前执行...");
    }

    /**
     * 后置通知，目标方法请求后会执行，无论正常执行还是出现异常了，都会执行
     */
    @After("execution(* com.itheima.service.impl.*.* (..))")
    public void afterAdvice(JoinPoint jp)  {
        log.info("后置通知，目标方法请求后执行...");
    }

    /**
     * 返回后通知，目标方法正常请求后会执行，出现异常不会执行
     */
    @AfterReturning("execution(* com.itheima.service.impl.*.* (..))")
    public void afterReturningAdvice(JoinPoint jp)  {
        log.info("返回后通知，目标方法正常请求后执行...");
    }

    /**
     * 异常后通知，目标方法出现异常后才会执行
     */
    @AfterThrowing("execution(* com.itheima.service.impl.*.* (..))")
    public void AfterThrowingAdvice(JoinPoint jp)  {
        log.info("异常后通知，目标方法异常请求后执行...");
    }
}
